#pragma once

#include<iostream>
#include<string>
#include<cstring>
#include<sys/types.h>
#include<sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <memory>
#include<unistd.h>
#define CONV(v) (struct sockaddr*)(v)
uint16_t Port_number = 8080;
std::string  IP_Address = "";
class udp_server
{
    public:
    udp_server()
    :_isrunning(false),
    _port(Port_number),
    _domain(-1)
    {
    }
    void server_Init()
    {
      _domain = socket(AF_INET,SOCK_DGRAM,0);
      if(_domain < 0)
      {
        std::cout << "socket_error" <<std::endl;
        return;
      }
      bzero(&_addr,sizeof(_addr));
      _addr.sin_port;
      _addr.sin_addr.s_addr = inet_addr(IP_Address.c_str());
      _addr.sin_port = htons(_port);
      _addr.sin_family = AF_INET;
      int n = bind(_domain,CONV(&_addr),sizeof(_addr));
      if(n < 0)
      {
        std::cout << "bind_error" << std::endl;
        return;
      }
      std::cout << "Init success" << std::endl;
    }
    void server_start()
    {
        _isrunning = true;
        while(true)
        {
            char massage[1024];
            sockaddr_in peer;
            socklen_t len = sizeof(peer);

            int n = recvfrom(_domain,massage,sizeof(massage)-1,0,CONV(&peer),&len);
            if(n > 0)
            {
                uint16_t post = ntohs(peer.sin_port);
                std::string ip = inet_ntoa(peer.sin_addr);
                massage[n] = 0;
                std::string clientinfo = ip + ":" + std::to_string(post) + " # " + massage;

                std::string echo_string = "echo# ";
                echo_string += massage;
                ::sendto(_domain,echo_string.c_str(),echo_string.size(),0,CONV(&peer),len);
            }
        }
        _isrunning = false;

    }
    ~udp_server()
    {
        if(_domain > -1)
        ::close(_domain);
    }
    private:
    sockaddr_in _addr;
    bool _isrunning;
    int _domain;
    uint16_t _port;
};